// ItgImage.h: interface for the McItgImage class.
//
//////////////////////////////////////////////////////////////////////

#ifndef _ITEGRAL_IMAGE_H_
#define _ITEGRAL_IMAGE_H_

#include "mcRaster.h"

typedef unsigned int sumtype;
typedef float sqsumtype;

// Integral image
class McItgImage  
{
public:
	McItgImage();
	virtual ~McItgImage();
	
	int		Prepare(const Raster<uchar> &srcimg, bool bexpend_one=false);

	inline	double	RectMean(const int left, const int top, const int right, const int bottom);
	inline	double	RectMean(irmm_Rect& rect){return RectMean(rect.left, rect.top, rect.right, rect.bottom);};
	inline	double	RectVar(const int left, const int top, const int right, const int bottom);
	inline	double	RectVar(irmm_Rect& rect){return RectVar(rect.left, rect.top, rect.right, rect.bottom);};
	inline	double	CalcuSTD(const int left, const int top, const int right, const int bottom);
	inline  double	CalcuSTD(irmm_Rect& rect){return CalcuSTD(rect.left, rect.top, rect.right, rect.bottom);};

	inline	double	HarrFeature(int type, int w, int h, int x, int y);
	
	inline	int		Width(void) const {return m_w;};
	inline  int		Height(void) const {return m_h;};

//private:
	unsigned			m_w;
	unsigned			m_h;
	double				m_std;
	Raster<sumtype>		ras_sum_image;
	Raster<sqsumtype>	ras_sq_image;
};

inline double McItgImage::RectMean(const int left, const int top, const int right, const int bottom)
{
	double a, b, c, d;

	d = ras_sum_image(bottom-1, right-1);

	if ((left == 0) || (top == 0))
		a = 0;
	else
		a = ras_sum_image(top-1, left-1);

	if (top == 0)
		b = 0;
	else
		b = ras_sum_image(top-1, right-1);

	if (left == 0)
		c = 0;
	else
		c = ras_sum_image(bottom-1, left-1);


	return (a + d - b - c) / ((right-left) * (bottom-top));
}

inline double McItgImage::RectVar(const int left, const int top, const int right, const int bottom)
{
	double a, b, c, d;

	d = ras_sq_image(bottom-1, right-1);

	if ((left == 0) || (top == 0))
		a = 0;
	else
		a = ras_sq_image(top - 1, left-1);

	if (top == 0)
		b = 0;
	else
		b = ras_sq_image(top - 1, right - 1);

	if (left == 0)
		c = 0;
	else
		c = ras_sq_image(bottom - 1, left - 1);


	return (a + d - b - c) / ((right-left) * (bottom-top));
}

//
//  Caculate the value of Harr-like feature
//  type:  1 --> left - right
//         2 --> up - down
//         3 --> center * 2 - two sides
//         4 --> diagnal - other diagnal
//
inline double McItgImage::HarrFeature(int type, int w, int h, int x, int y)
{
	double retval = 0;

	double vleft, vright, vtop, vdown, vmiddle, vlt, vrt, vlb, vrb;
	switch(type)
	{
	case 1:
		vleft  = RectMean(x, y, x+w, y+h);
		vright = RectMean(x+w, y, x+w+ w, y+h);
		retval = vleft - vright;
		break;
	case 2:
		vtop  = RectMean(x, y, x + w, y + h);
		vdown = RectMean(x, y + h, x + w, y + h + h);
		retval = vtop - vdown;
		break;
	case 3:
		vleft   = RectMean(x, y, x + w, y + h);
		vmiddle = RectMean(x + w, y, x + w + w, y + h);
		vright  = RectMean(x + w + w, y, x + w + w + w, y + h);
		retval = vmiddle * 2 - vleft - vright;
		break;
	case 4:
		vlt   = RectMean(x, y, x + w, y + h);
		vrt   = RectMean(x + w, y, x + w + w, y + h);
		vlb   = RectMean(x, y + h, x + w, y + h + h);
		vrb   = RectMean(x + w, y + h, x + w + w, y + h + h);
		retval = vlt + vrb - vrt - vlb;
		break;
	default:;
		//printf("\nMcItgImage::HarrFeature: error feature type!\n");
	}
	return retval;
}


inline double McItgImage::CalcuSTD(const int left, const int top, const int right, const int bottom)
{
/*	assert(r.left < r.right);
	assert(r.top < r.bottom);
	assert(r.left >= 0);
	assert(r.top >= 0);
	assert(r.right <= m_w);
	assert(r.bottom <= m_h);
*/
	double m = RectMean(left, top, right, bottom);
	double var = RectVar(left, top, right, bottom);

	return sqrt(var - m * m);
}



#endif
